#!/usr/bin/python

import os
import sys
#topo
pci_map = {
    "41:00.0":"00:0a.0",
    "41:00.1":"00:0b.0",
    "42:00.0":"00:0c.0",
    "42:00.1":"00:0d.0",
    "81:00.0":"00:0e.0",
    "81:00.1":"00:09.0",
    "82:00.0":"00:0f.0",
    "82:00.1":"00:10.0",
    "c1:00.0":"00:11.0",
    "c1:00.1":"00:12.0",
    "c2:00.0":"00:13.0",
    "c2:00.1":"00:14.0",
    }
ovs_topo ={
    "R930":{
        "sw19":[["sw20",11,1],["sw1",11,0],["sw18",12,0]],
        "sw20":[["sw19",194,0],["sw3",194,1]],
        "sw18":[["sw19",129,1],["h3",130,0],["sw17",129,0]],
        "sw17":[["sw18",66,1],["sw13",193,0]],
        "sw15":[["sw13",65,1],["sw16",65,0]],
        "sw16":[["sw15",66,0],["sw3",193,1],["sw8",130,1]],
    },
    # "smart-route-ovs":{
    #     "sw20":[["sw19",194,0],["sw3",194,1]],
    #     "sw18":[["sw19",129,1],["h3",130,0],["sw17",129,0]],
    #     "sw17":[["sw18",66,1],["sw13",193,0]],
    #     "sw15":[["sw13",65,1],["sw16",65,0]],
    #     "sw16":[["sw15",66,0],["sw3",193,1],["sw8",130,1]],
    # },
    "net1":{
        "sw1":[["sw2",23,0],["sw19",23,1],["h1"]],
        "sw2":[["sw1",1,0],["sw3",1,1]],
        "sw3":[["sw2",49,0],["sw4",177,0],["sw5",152,1],["sw16",152,0],["sw20",49,1],["h10"]],
        "sw4":[["sw3",177,1],["h9"]],
        "sw5":[["sw3",202,0],["sw6",202,1]],
    }
}

controller_addr = "10.112.132.216:6633"


def add_and_set_sw(machine="net1"):
    cmd = ""

    #add br
    for sw in ovs_topo[machine].keys():
        cmd += f'ovs-vsctl add-br {sw} -- set Bridge {sw} datapath_type=netdev\n'

    cmd +=add_and_set_interface(machine=machine)
    return cmd
    
def add_and_set_interface(machine="net1"):
    cmd = ""
    for sw,ports in ovs_topo[machine].items():
        for port in ports:
            # pci类型
            if len(port) == 3:
                port_name = f'{sw}-{port[0]}'
                if machine == "smart-route-ovs":
                    pci = pci_map[f'{port[1]:02x}:00.{port[2]}']
                else:
                    pci = f'{port[1]:02x}:00.{port[2]}'
                speeds = "1G" if "sw" in port[0] else "auto"
                cmd += f'ovs-vsctl add-port {sw} {port_name} -- set Interface {port_name} type=dpdk options:speeds={speeds} options:dpdk-devargs={pci}\n'    
            # vhost类型
            elif len(port) == 1:
                port_name = f'{sw}-{port[0]}'
                cmd += f'ovs-vsctl add-port {sw} {port_name} -- set Interface {port_name} type=dpdkvhostuserclient options:vhost-server-path=/tmp/{port[0]}-{sw}.sock\n'
    return cmd


def set_interface(machine="smart-route-ovs"):
    cmd = ""
    for sw,ports in ovs_topo[machine].items():
        for port in ports: 
            # pci类型
            if len(port) == 3:
                port_name = f'{sw}-{port[0]}'
                if machine == "smart-route-ovs":
                    pci = pci_map[f'{port[1]:02x}:00.{port[2]}']
                else:
                    pci = f'{port[1]:02x}:00.{port[2]}'
                cmd += f'ovs-vsctl set Interface {port_name} type=dpdk options:speeds=1G options:dpdk-devargs={pci}\n'    
            # vhost类型
            elif len(port) == 1:
                port_name = f'{sw}-{port[0]}'
                cmd += f'ovs-vsctl set Interface {port_name} type=dpdkvhostuserclient options:vhost-server-path=/tmp/{port[0]}-{sw}.sock\n'
    return cmd


def set_controller(machine="net1"):
    commands=""
    brs = ovs_topo[machine].keys()
    for br in brs:
        commands += f'ovs-vsctl set-controller {br} tcp:{controller_addr}\n'
        dpid = int(br[2:])
        commands += f'ovs-vsctl set bridge {br} other_config:datapath-id={dpid:016X}\n'
        commands += f'ovs-vsctl set bridge {br} fail_mode=secure\n'
    return commands

cmds = [
    add_and_set_sw,
    set_interface,
    set_controller
]

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print(f"请输入hostname, 选择其中一个: {list(ovs_topo.keys())}")
        sys.exit(1)

    for i in range(len(cmds)):
        print(f'[{i}]: {cmds[i].__name__}')
    index = int(input("输入命令编号:"))
    print(cmds[index](machine=sys.argv[1]))
    os.popen(cmds[index](machine=sys.argv[1]))